
#include <bur/plctypes.h>
#ifdef __cplusplus
	extern "C"
	{
#endif
	#include "helper_nc.h"
#ifdef __cplusplus
	};
#endif

typedef unsigned char (*nc_check_fun)(unsigned long);
/* TODO: Add your comment here */
void nc_executor(struct nc_executor* inst)
{
	/*TODO: Add your code here*/
	switch (inst->step)
	{
		// idle
		case 0:
			if (inst->execute == 1)
			{
				inst->execute = 0;
				inst->entry_processed = 0;
				if (inst->entry_num == 0)
					break;
				if ((inst->object == 0) || inst->entry_num > sizeof(inst->entry)/sizeof(inst->entry[0]))
				{
					inst->status = NCEXEC_INVALID_INPUT;
				}
				else
				{
					inst->step = 1;
					inst->status = NCEXEC_BUSY;
				}
			}
			break;
		
		// call ncation
		case 1:
			if ( (inst->entry[inst->entry_processed].subject == 0) || (inst->entry[inst->entry_processed].action == 0) || 
				((unsigned long)inst->entry[inst->entry_processed].check.function == 0 && inst->entry[inst->entry_processed].check.offset == 0))
			{
				inst->step = 0;
				inst->status = NCEXEC_INVALID_INPUT;
				break;
			}
			
			inst->status = ncaction(inst->object, inst->entry[inst->entry_processed].subject, inst->entry[inst->entry_processed].action);
			if (inst->status == ncOK)
				inst->step = 2;
			else if (inst->status == ncACTIVE);
			else
			{
				inst->step = 0; // nc action error occured
			}
			break;
		
		// wait ncation
		case 2:
			if ((unsigned long)inst->entry[inst->entry_processed].check.function != 0)
			{
				if (!((nc_check_fun)(inst->entry[inst->entry_processed].check.function))(inst->object))
					break;
			}
			else
			{
				if (*(unsigned char*)(inst->object + inst->entry[inst->entry_processed].check.offset) != inst->entry[inst->entry_processed].check.value)
					break;
			}
			inst->entry_processed++;
			if (inst->entry_processed == inst->entry_num)
			{
				inst->step = 0;
				inst->entry_num = 0;
				inst->status = NCEXEC_SUCCESS;	
			}
			else
				inst->step = 1;
			break;
	}
}

signed long nc_set_entry(struct nc_entry_t* inst, unsigned short subject ,unsigned short action, unsigned short check_offset, unsigned short check_value, unsigned long check_function)
{
	inst->subject = subject;
	inst->action = action;
	inst->check.offset = check_offset;
	inst->check.value = check_value;
	inst->check.function = check_function;
	return 0;
}

signed long nc_add_entry(struct nc_executor* inst, unsigned short subject ,unsigned short action, unsigned short check_offset, unsigned short check_value, unsigned long check_function)
{
	if (inst->entry_num >= ENTRY_BUF_SIZE) return -1;
	inst->entry[inst->entry_num].subject = subject;
	inst->entry[inst->entry_num].action = action;
	inst->entry[inst->entry_num].check.offset = check_offset;
	inst->entry[inst->entry_num].check.value = check_value;
	inst->entry[inst->entry_num].check.function = check_function;
	inst->entry_num++;
	return 0;
}

unsigned char nc_check_service_rwpar(unsigned long object)
{
	ACP10AXIS_typ* p_ax = (ACP10AXIS_typ*)object;
	return p_ax->network.service.request.par_id == p_ax->network.service.response.par_id;
}

unsigned char nc_check_nocheck(unsigned long object)
{
	return 1;
}

